#pragma once             // 防止头文件被重复包含
#include "Log.hpp"       // 引入自定义的日志头文件
#include <iostream>      // 用于标准输入输出流
#include <unordered_map> // 用于实现哈希表（字典）
#include <fstream>       // 用于文件输入输出操作
#include <string>        // 用于字符串操作

// 定义一个名为 dict_ns 的命名空间，用于封装词典相关的类和常量
namespace dict_ns
{
    // 定义默认的词典文件路径常量
    const std::string defaultpath = "./Dict.txt";
    // 定义词典文件中单词和释义之间的分隔符常量
    const std::string sep = ": ";

    // 定义一个名为 Dict 的类，用于管理和操作词典数据
    class Dict
    {
    private:
        // 私有成员函数，用于从词典文件中加载数据到内存
        bool Load()
        {
            // 创建一个输入文件流对象，并尝试打开词典文件
            std::ifstream in(_dict_conf_filepath);
            // 检查文件是否成功打开
            if (!in.is_open())
            {
                // 如果文件打开失败，记录致命错误日志并返回 false
                LOG(FATAL, "open %s error\n", _dict_conf_filepath.c_str());
                return false;
            }
            // 定义一个字符串变量，用于存储从文件中读取的每一行
            std::string line;
            // 循环读取文件的每一行，直到文件末尾
            while (std::getline(in, line))
            {
                // 如果读取的行是空的，则跳过当前行
                if (line.empty())
                    continue;
                // 查找分隔符在当前行中的位置
                auto pos = line.find(sep); // [happy): 快乐的    [abcde)fg
                // 如果没有找到分隔符，则跳过当前行
                if (pos == std::string::npos)
                    continue;
                // 提取分隔符之前的子字符串作为单词
                std::string word = line.substr(0, pos); // pos位置的下标就是pos位置之前元素的个数
                // 如果提取的单词是空的，则跳过当前行
                if (word.empty())
                    continue;
                // 提取分隔符之后的子字符串作为释义
                std::string han = line.substr(pos + sep.size());
                // 如果提取的释义是空的，则跳过当前行
                if (han.empty())
                    continue;
                // 记录调试日志，显示加载的单词和释义信息
                LOG(DEBUG, "load info, %s: %s\n", word.c_str(), han.c_str());

                // 将提取的单词和释义作为键值对插入到 _dict 哈希表中
                _dict.insert(std::make_pair(word, han));
            }
            // 关闭文件流
            in.close();
            // 记录调试日志，表示词典文件加载成功
            LOG(DEBUG, "load %s success\n", _dict_conf_filepath.c_str());
            // 返回 true 表示加载成功
            return true;
        }

    public:
        // 构造函数，接收一个可选的词典文件路径参数，默认为 defaultpath
        Dict(const std::string &path = defaultpath) : _dict_conf_filepath(path)
        {
            // 在构造对象时调用 Load() 方法加载词典数据
            Load();
        }
        // 公有成员函数，用于翻译给定的英文单词
        // word: 需要翻译的英文单词
        // ok: 引用参数，用于指示翻译是否成功
        // 返回值: 如果找到单词，返回对应的中文释义；否则返回 "未找到"
        std::string Translate(const std::string &word, bool &ok) const
        {
            // 默认设置翻译成功
            ok = true;
            // 在 _dict 哈希表中查找给定的单词
            auto iter = _dict.find(word);
            // 如果没有找到单词 (迭代器指向哈希表末尾)
            if (iter == _dict.end())
            {
                // 设置翻译失败
                ok = false;
                // 返回 "未找到"
                return "未找到";
            }
            // return _dict[word]; // 也可以使用 operator[] 获取值，但 find 更安全，因为它不会在键不存在时插入新元素
            // 返回找到的单词对应的释义
            return iter->second;
        }
        // 析构函数，目前为空，因为没有需要手动释放的动态分配资源 (unordered_map 会自动管理内存)
        ~Dict() = default;

    private:
        // 私有成员变量，用于存储词典数据的哈希表 (英文单词 -> 中文释义)
        std::unordered_map<std::string, std::string> _dict;
        // 私有成员变量，用于存储词典文件的路径
        std::string _dict_conf_filepath;
    };
} // namespace dict_ns